package com.rolerealm.service.impl;

import com.rolerealm.dao.CharacterMapper;
import com.rolerealm.dao.UserInteractionMapper;
import com.rolerealm.domain.dto.RecommendationRequestDTO;
import com.rolerealm.domain.entity.CharacterEntity;
import com.rolerealm.domain.entity.UserInteractionEntity;
import com.rolerealm.domain.enums.RecommendationStrategy;
import com.rolerealm.domain.vo.CharacterVO;
import com.rolerealm.domain.vo.PageResult;
import com.rolerealm.domain.vo.UserInteractionVO;
import com.rolerealm.service.RecommendationService;
import com.rolerealm.service.UserInteractionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 推荐服务实现类
 * 
 * @author RoleRealm Team
 * @version 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RecommendationServiceImpl implements RecommendationService {

    private final CharacterMapper characterMapper;
    private final UserInteractionMapper userInteractionMapper;
    private final UserInteractionService userInteractionService;

    @Override
    public PageResult<CharacterVO> getRecommendedCharacters(Long userId, Integer page, Integer size) {
        log.debug("获取用户推荐角色，用户ID：{}，页码：{}，每页大小：{}", userId, page, size);
        
        // 获取用户行为数据
        List<UserInteractionVO> interactions = userInteractionService.getUserInteractions(userId, 30);
        
        // 基于行为数据计算推荐
        List<Long> recommendedCharacterIds = calculateRecommendations(interactions, userId);
        
        if (CollectionUtils.isEmpty(recommendedCharacterIds)) {
            // 冷启动：返回热门角色
            recommendedCharacterIds = getPopularCharacterIds(size * 2);
        }
        
        // 分页处理
        int startIndex = (page - 1) * size;
        int endIndex = Math.min(startIndex + size, recommendedCharacterIds.size());
        if (startIndex >= endIndex) {
            return PageResult.of(Collections.emptyList(), page, size, (long) recommendedCharacterIds.size());
        }
        List<Long> pagedCharacterIds = recommendedCharacterIds.subList(startIndex, endIndex);
        if (pagedCharacterIds.isEmpty()) {
            return PageResult.of(Collections.emptyList(), page, size, (long) recommendedCharacterIds.size());
        }
        
        // 查询角色信息（避免 IN () 语法错误）
        List<CharacterEntity> characters = characterMapper.selectByIds(pagedCharacterIds);
        
        // 转换为VO
        List<CharacterVO> characterVOs = characters.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        return PageResult.of(characterVOs, page, size, (long) recommendedCharacterIds.size());
    }

    @Override
    public void refreshUserRecommendations(Long userId) {
        log.debug("刷新用户推荐结果，用户ID：{}", userId);
        
        // 清除现有缓存
        clearUserRecommendations(userId);
        
        // 重新计算推荐结果
        getRecommendedCharacters(userId, 1, 10);
        
        log.debug("用户推荐结果刷新完成，用户ID：{}", userId);
    }

    @Override
    public List<CharacterVO> getRecommendedCharacters(RecommendationRequestDTO request) {
        log.debug("根据推荐请求获取推荐结果，请求：{}", request);
        
        RecommendationStrategy strategy = RecommendationStrategy.getByCode(request.getStrategy());
        
        switch (strategy) {
            case COLLABORATIVE_FILTERING:
                return getCollaborativeFilteringRecommendations(request);
            case CONTENT_BASED:
                return getContentBasedRecommendations(request.getUserId(), request.getLimit());
            case POPULARITY:
                return getPopularRecommendations(request.getLimit());
            case RANDOM:
                return getRandomRecommendations(request);
            case SKILL_BASED:
                return getSkillBasedRecommendations(request.getUserId(), request.getPreferredSkillTypes(), request.getLimit());
            case CATEGORY_BASED:
                return getCategoryBasedRecommendations(request);
            case HYBRID:
                return getHybridRecommendations(request);
            default:
                return getCollaborativeFilteringRecommendations(request);
        }
    }

    @Override
    public List<CharacterVO> getPopularRecommendations(Integer limit) {
        log.debug("获取热门角色推荐，限制数量：{}", limit);
        
        List<CharacterEntity> characters = characterMapper.selectPopularCharacters(limit);
        
        return characters.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<CharacterVO> getContentBasedRecommendations(Long userId, Integer limit) {
        log.debug("获取基于内容的推荐，用户ID：{}，限制数量：{}", userId, limit);
        
        // 获取用户历史交互的角色
        List<UserInteractionVO> interactions = userInteractionService.getUserInteractions(userId, 30);
        
        if (CollectionUtils.isEmpty(interactions)) {
            return getPopularRecommendations(limit);
        }
        
        // 分析用户偏好
        Map<String, Integer> categoryPrefs = new HashMap<>();
        Map<String, Integer> skillTypePrefs = new HashMap<>();
        Map<String, Integer> eraPrefs = new HashMap<>();
        
        for (UserInteractionVO interaction : interactions) {
            CharacterEntity character = characterMapper.selectById(interaction.getCharacterId());
            if (character != null) {
                categoryPrefs.merge(character.getCategory(), 1, Integer::sum);
                skillTypePrefs.merge(character.getSkillType(), 1, Integer::sum);
                eraPrefs.merge(character.getEra(), 1, Integer::sum);
            }
        }
        
        // 根据偏好推荐相似角色
        return getCharactersByPreferences(categoryPrefs, skillTypePrefs, eraPrefs, limit);
    }

    @Override
    public List<CharacterVO> getSkillBasedRecommendations(Long userId, List<String> skillTypes, Integer limit) {
        log.debug("获取基于技能的推荐，用户ID：{}，技能类型：{}，限制数量：{}", userId, skillTypes, limit);
        
        if (CollectionUtils.isEmpty(skillTypes)) {
            return getPopularRecommendations(limit);
        }
        
        List<CharacterEntity> characters = new ArrayList<>();
        for (String skillType : skillTypes) {
            List<CharacterEntity> skillCharacters = characterMapper.selectBySkillType(skillType, limit / skillTypes.size() + 1);
            characters.addAll(skillCharacters);
        }
        
        // 去重并限制数量
        return characters.stream()
                .distinct()
                .limit(limit)
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<CharacterVO> getHybridRecommendations(RecommendationRequestDTO request) {
        log.debug("获取混合推荐结果，请求：{}", request);
        
        List<CharacterVO> recommendations = new ArrayList<>();
        
        // 协同过滤推荐 (40%)
        List<CharacterVO> collaborativeRecs = getCollaborativeFilteringRecommendations(request);
        recommendations.addAll(collaborativeRecs.subList(0, Math.min(collaborativeRecs.size(), request.getLimit() * 4 / 10)));
        
        // 基于内容的推荐 (30%)
        List<CharacterVO> contentRecs = getContentBasedRecommendations(request.getUserId(), request.getLimit() * 3 / 10);
        recommendations.addAll(contentRecs);
        
        // 热门推荐 (20%)
        if (request.getIncludePopular() != null && request.getIncludePopular()) {
            List<CharacterVO> popularRecs = getPopularRecommendations(request.getLimit() * 2 / 10);
            recommendations.addAll(popularRecs);
        }
        
        // 随机推荐 (10%)
        if (request.getIncludeRandom() != null && request.getIncludeRandom()) {
            List<CharacterVO> randomRecs = getRandomRecommendations(request);
            recommendations.addAll(randomRecs.subList(0, Math.min(randomRecs.size(), request.getLimit() / 10)));
        }
        
        // 去重并限制数量
        return recommendations.stream()
                .distinct()
                .limit(request.getLimit())
                .collect(Collectors.toList());
    }

    @Override
    public void clearUserRecommendations(Long userId) {
        log.debug("清除用户推荐缓存，用户ID：{}", userId);
        
        // 这里可以添加Redis缓存清除逻辑
        // 暂时只记录日志
        log.debug("用户推荐缓存清除完成，用户ID：{}", userId);
    }

    /**
     * 基于协同过滤算法计算推荐结果
     */
    private List<Long> calculateRecommendations(List<UserInteractionVO> userInteractions, Long userId) {
        if (CollectionUtils.isEmpty(userInteractions)) {
            return Collections.emptyList();
        }
        
        // 获取用户交互过的角色ID
        Set<Long> userCharacterIds = userInteractions.stream()
                .map(UserInteractionVO::getCharacterId)
                .collect(Collectors.toSet());
        
        // 获取相似用户
        List<Long> similarUserIds = userInteractionMapper.selectSimilarUserIds(userId, 10);
        
        if (CollectionUtils.isEmpty(similarUserIds)) {
            return Collections.emptyList();
        }
        
        // 收集相似用户交互的角色
        Map<Long, Integer> characterScores = new HashMap<>();
        
        for (Long similarUserId : similarUserIds) {
            List<UserInteractionEntity> similarUserInteractions = userInteractionMapper.selectByUserId(similarUserId, 50);
            
            for (UserInteractionEntity interaction : similarUserInteractions) {
                Long characterId = interaction.getCharacterId();
                
                // 跳过用户已经交互过的角色
                if (userCharacterIds.contains(characterId)) {
                    continue;
                }
                
                // 计算角色得分
                int score = calculateCharacterScore(interaction);
                characterScores.merge(characterId, score, Integer::sum);
            }
        }
        
        // 按得分排序并返回角色ID列表
        return characterScores.entrySet().stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

    /**
     * 计算角色得分
     */
    private int calculateCharacterScore(UserInteractionEntity interaction) {
        int baseScore = 1;
        
        // 根据交互类型调整得分
        switch (interaction.getInteractionType()) {
            case "chat":
                baseScore = 3;
                break;
            case "favorite":
                baseScore = 5;
                break;
            case "view":
                baseScore = 1;
                break;
            default:
                baseScore = 1;
        }
        
        // 根据交互时长调整得分
        if (interaction.getDurationSeconds() != null) {
            if (interaction.getDurationSeconds() > 300) { // 5分钟以上
                baseScore *= 2;
            } else if (interaction.getDurationSeconds() > 60) { // 1分钟以上
                baseScore = (int) (baseScore * 1.5);
            }
        }
        
        return baseScore;
    }

    /**
     * 获取热门角色ID列表
     */
    private List<Long> getPopularCharacterIds(Integer limit) {
        List<CharacterEntity> popularCharacters = characterMapper.selectPopularCharacters(limit);
        return popularCharacters.stream()
                .map(CharacterEntity::getId)
                .collect(Collectors.toList());
    }

    /**
     * 协同过滤推荐
     */
    private List<CharacterVO> getCollaborativeFilteringRecommendations(RecommendationRequestDTO request) {
        List<UserInteractionVO> interactions = userInteractionService.getUserInteractions(request.getUserId(), 30);
        List<Long> recommendedCharacterIds = calculateRecommendations(interactions, request.getUserId());
        
        if (CollectionUtils.isEmpty(recommendedCharacterIds)) {
            return getPopularRecommendations(request.getLimit());
        }
        
        List<CharacterEntity> characters = characterMapper.selectByIds(recommendedCharacterIds);
        return characters.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 随机推荐
     */
    private List<CharacterVO> getRandomRecommendations(RecommendationRequestDTO request) {
        // 获取所有角色
        List<CharacterEntity> allCharacters = characterMapper.selectList(null);
        
        // 随机选择
        Collections.shuffle(allCharacters);
        
        return allCharacters.stream()
                .limit(request.getLimit())
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 基于分类的推荐
     */
    private List<CharacterVO> getCategoryBasedRecommendations(RecommendationRequestDTO request) {
        if (CollectionUtils.isEmpty(request.getPreferredCategories())) {
            return getPopularRecommendations(request.getLimit());
        }
        
        List<CharacterEntity> characters = new ArrayList<>();
        for (String category : request.getPreferredCategories()) {
            // 这里需要添加按分类查询的方法
            // 暂时使用现有方法
            List<CharacterEntity> categoryCharacters = characterMapper.selectBySkillType(category, request.getLimit() / request.getPreferredCategories().size() + 1);
            characters.addAll(categoryCharacters);
        }
        
        return characters.stream()
                .distinct()
                .limit(request.getLimit())
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 根据用户偏好获取角色
     */
    private List<CharacterVO> getCharactersByPreferences(Map<String, Integer> categoryPrefs, 
                                                         Map<String, Integer> skillTypePrefs, 
                                                         Map<String, Integer> eraPrefs, 
                                                         Integer limit) {
        // 获取所有角色
        List<CharacterEntity> allCharacters = characterMapper.selectList(null);
        
        // 计算角色得分
        Map<Long, Integer> characterScores = new HashMap<>();
        
        for (CharacterEntity character : allCharacters) {
            int score = 0;
            score += categoryPrefs.getOrDefault(character.getCategory(), 0) * 3;
            score += skillTypePrefs.getOrDefault(character.getSkillType(), 0) * 2;
            score += eraPrefs.getOrDefault(character.getEra(), 0) * 1;
            
            if (score > 0) {
                characterScores.put(character.getId(), score);
            }
        }
        
        // 按得分排序
        return characterScores.entrySet().stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .limit(limit)
                .map(entry -> {
                    CharacterEntity character = allCharacters.stream()
                            .filter(c -> c.getId().equals(entry.getKey()))
                            .findFirst()
                            .orElse(null);
                    return character != null ? convertToVO(character) : null;
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 转换为角色VO
     */
    private CharacterVO convertToVO(CharacterEntity entity) {
        CharacterVO vo = new CharacterVO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
